﻿//IConnectionWrapper.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Plaza.Wrappers
{
	using System;

	using Ecng.Common;

	/// <summary>
	/// Статус подключения.
	/// </summary>
	[Flags]
	enum ConnectionWrapperStatus
	{
		/// <summary>
		/// Соединение с роутером еще не установлено.
		/// </summary>
		Disconnected = 1,

		/// <summary>
		/// Соединение с роутером установлено.
		/// </summary>
		Connected = 2,

		/// <summary>
		/// Нарушен протокол работы соединения, дальнейшая работа возможна только после повторной установки соединения. 
		/// </summary>
		Invalid = 4,

		/// <summary>
		/// Соединение временно заблокировано функцией получения сообщения.
		/// </summary>
		Busy = 8,

		/// <summary>
		/// Роутер запущен, но не присоединен к сети.
		/// </summary>
		RouterDisconnected = 65536,

		/// <summary>
		/// Роутер получил аутентификационную информацию (имя и пароль), пытается установить исходящее соединение, но ни одно исходящее соединение еще не установлено.
		/// </summary>
		RouterReconnecting = 131072,

		/// <summary>
		/// Роутер установил по крайней мере одно исходящее соединение, аутентификационная информация подтверждена.
		/// </summary>
		RouterConnected = 262144,

		/// <summary>
		/// По крайней мере один из сервисов отклонил аутентификационную информацию. 
		/// </summary>
		RouterLoginFailed = 524288,

		/// <summary>
		/// За заданное количество попыток роутер не смог установить ни одного исходящего соединения, но аутентификационная информация подтверждена.
		/// </summary>
		RouterNoConnect = 1048576,
	}

	/// <summary>
	/// Создание и работа с соединениями, а также приема и обработки сообщений.
	/// </summary>
	interface IConnectionWrapper
	{
		/// <summary>
		/// IP-адрес узла либо UNC-имя.
		/// </summary>
		string Host { get; set; }

		/// <summary>
		/// Номер порта TCP/IP.
		/// </summary>
		uint Port { get; set; }

		/// <summary>
		/// Имя приложения, для которого необходимо установить соединение.
		/// </summary>
		string AppName { get; set; }

		/// <summary>
		/// Пароль для локального соединения.
		/// </summary>
		string Password { set; }

		/// <summary>
		/// С аутентификационной информацией роутера.
		/// </summary>
		string LoginStr { get; set; }

		/// <summary>
		/// Cостояние соединения или роутера.
		/// </summary>
		ConnectionWrapperStatus Status { get; }

		/// <summary>
		/// Разрыв всех удаленных соединений роутера.
		/// </summary>
		void Logout();

		/// <summary>
		/// Разрыв локального соединения.
		/// </summary>
		void Disconnect();

		/// <summary>
		/// Инициирование входа роутера в сеть.
		/// </summary>
		void Login();

		/// <summary>
		/// Создание локального соединения приложения с роутером.
		/// </summary>
		/// <returns></returns>
		long Connect();

		/// <summary>
		/// Создание локального соединения приложения с роутером.
		/// </summary>
		/// <param name="connStr">Строка с параметрами соединения.</param>
		/// <returns></returns>
		long Connect(string connStr);

		/// <summary>
		/// Получение полного адреса приложения по имени сервиса, который оно предоставляет.
		/// </summary>
		/// <param name="service">Имя сервиса.</param>
		/// <returns></returns>
		string ResolveService(string service);

		/// <summary>
		/// Прием и обработка сообщений, в том числе и репликационных.
		/// </summary>
		/// <param name="pollTimeout"></param>
		void ProcessMessage(TimeSpan pollTimeout);

		/// <summary>
		/// Нотификация об изменении состояния соединения или роутера.
		/// </summary>
		event Action<IConnectionWrapper, ConnectionWrapperStatus> ConnectionStatusChanged;
	}

	class ConnectionWrapper32 : IConnectionWrapper
	{
		internal readonly P2ClientGateMTA32.CP2ConnectionClass Connection;

		public ConnectionWrapper32()
		{
			Connection = new P2ClientGateMTA32.CP2ConnectionClass();
			Connection.ConnectionStatusChanged += (a, b) => OnConnectionStatusChanged((ConnectionWrapperStatus)b);
		}

		public void Login()
		{
			Connection.Login();
		}

		public long Connect()
		{
			return Connection.Connect();
		}

		public void Logout()
		{
			Connection.Logout();
		}

		public void Disconnect()
		{
			Connection.Disconnect();
		}

		public string ResolveService(string service)
		{
			return Connection.ResolveService(service);
		}

		public void ProcessMessage(TimeSpan pollTimeout)
		{
			uint cookie;
			Connection.ProcessMessage(out cookie, (uint)pollTimeout.TotalMilliseconds);
		}

		public ConnectionWrapperStatus Status
		{
			get { return (ConnectionWrapperStatus)Connection.Status; }
		}

		public long Connect(string connStr)
		{
			return Connection.Connect2(connStr);
		}

		public string Host
		{
			get { return Connection.Host; }
			set { Connection.Host = value; }
		}

		public uint Port
		{
			get { return Connection.Port; }
			set { Connection.Port = value; }
		}

		public string AppName
		{
			get { return Connection.AppName; }
			set { Connection.AppName = value; }
		}

		public string Password
		{
			set { Connection.Password = value; }
		}

		public string LoginStr
		{
			get { return Connection.LoginStr; }
			set { Connection.LoginStr = value; }
		}

		public event Action<IConnectionWrapper, ConnectionWrapperStatus> ConnectionStatusChanged;

		public void OnConnectionStatusChanged(ConnectionWrapperStatus wrapperStatus)
		{
			ConnectionStatusChanged.SafeInvoke(this, wrapperStatus);
		}
	}

	class ConnectionWrapper64 : IConnectionWrapper
	{
		internal readonly P2ClientGateMTA64.CP2ConnectionClass Connection;

		public ConnectionWrapper64()
		{
			Connection = new P2ClientGateMTA64.CP2ConnectionClass();
			Connection.ConnectionStatusChanged += (a, b) => OnConnectionStatusChanged((ConnectionWrapperStatus)b);
		}

		public void Login()
		{
			Connection.Login();
		}

		public Int64 Connect()
		{
			return Connection.Connect();
		}

		public void Logout()
		{
			Connection.Logout();
		}

		public void Disconnect()
		{
			Connection.Disconnect();
		}

		public string ResolveService(string service)
		{
			return Connection.ResolveService(service);
		}

		public void ProcessMessage(TimeSpan pollTimeout)
		{
			uint cookie;
			Connection.ProcessMessage(out cookie, (uint)pollTimeout.TotalMilliseconds);
		}

		public ConnectionWrapperStatus Status
		{
			get { return (ConnectionWrapperStatus)Connection.Status; }
		}

		public long Connect(string connStr)
		{
			return Connection.Connect2(connStr);
		}

		public string Host
		{
			get { return Connection.Host; }
			set { Connection.Host = value; }
		}

		public uint Port
		{
			get { return Connection.Port; }
			set { Connection.Port = value; }
		}

		public string AppName
		{
			get { return Connection.AppName; }
			set { Connection.AppName = value; }
		}

		public string Password
		{
			set { Connection.Password = value; }
		}

		public string LoginStr
		{
			get { return Connection.LoginStr; }
			set { Connection.LoginStr = value; }
		}

		public event Action<IConnectionWrapper, ConnectionWrapperStatus> ConnectionStatusChanged;

		public void OnConnectionStatusChanged(ConnectionWrapperStatus wrapperStatus)
		{
			ConnectionStatusChanged.SafeInvoke(this, wrapperStatus);
		}
	}
}